package com.tbit.uqbike.push.service.impl;

import com.tbit.uqbike.push.constant.ControlTypeConstant;
import com.tbit.uqbike.push.constant.RedisConstant;
import com.tbit.uqbike.push.constant.SystemData;
import com.tbit.uqbike.push.dao.core.AccountConfigExtDao;
import com.tbit.uqbike.push.dao.core.CallConfigDao;
import com.tbit.uqbike.push.pojo.*;
import com.tbit.uqbike.push.service.RedisService;
import com.tbit.uqbike.push.service.TerControlService;
import com.tbit.uqbike.push.service.ThreadService;
import com.tbit.uqbike.push.util.CallHttpClient;
import com.tbit.uqbike.push.util.DateTimeUtil;
import com.tbit.uqbike.push.util.LogUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.Optional;
import java.util.UUID;


/**
 * @author chenmengran
 * @Description: 线程操作
 * @date 2019\6\17 00179:23
 */
@Slf4j
public class ThreadServiceImpl implements ThreadService {

    //线程传参
    private RedisService redisService;
    private TerControlService terControlService;
    private User user;
    private String machineNO;
    private Geo geo;
    private TerPosition terPosition;
    private AccountConfigExtDao accountConfigExtDao;

    private CallConfigDao callConfigDao;

    public void setRedisService(RedisService redisService) {
        this.redisService = redisService;
    }

    public void setTerPosition(TerPosition terPosition) {
        this.terPosition = terPosition;
    }

    public void setAccountConfigExtDao(AccountConfigExtDao accountConfigExtDao) {
        this.accountConfigExtDao = accountConfigExtDao;
    }

    public void setTerControlService(TerControlService terControlService) {
        this.terControlService = terControlService;
    }

    public void setCallConfigDao(CallConfigDao callConfigDao) {
        this.callConfigDao = callConfigDao;
    }

    public void setMachineNO(String machineNO) {
        this.machineNO = machineNO;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public void setGeo(Geo geo) {
        this.geo = geo;
    }

    @Override
    public void outsidePush() {
        /**默认断电时间*/
        if (geo.getCutTimeLong() == null) {
            geo.setCutTimeLong(0);
        }

        //语音通知
        String msgVoice = redisService.get("msgVoice" + machineNO);
        try {
            if (msgVoice != null && Integer.valueOf(msgVoice) == 1) {
                LogUtil.info("machineNO=" + machineNO + "语音给用户");
                /**兼容寻呼可配置*/
                CallConfig callConfig = callConfigDao.getByAccountId(geo.getAccountId());
                if (callConfig != null) {
                    CallHttpClient.callByModelId(user.getPhone(), callConfig.getAppCode(), callConfig.getTplId());
                } else {
                    CallHttpClient.call(user.getPhone());
                }
                redisService.add("msgVoice" + machineNO, "0");
            }
        } catch (Exception e) {
            LogUtil.info("machineNO=" + machineNO + "语音给用户异常");
        }

        try {
            /**语音播报*/
            //Boolean terPower = TerminalUtils.testBit(Integer.valueOf(terPosition.getCarStatus()), 1);
            /**车辆是否是运动状态*/
            //if (terPower) {
            //语音播放3分钟
            String voiceTimeS = SystemData.geoViceTime.get(machineNO);
            //语音间隔15秒
            String sendTimeS = SystemData.geoSendTime.get(machineNO);
            //语音播放3次
            /*Integer num = SystemData.geoViceTice.get(machineNO);
            if (num == null) {
              num = 1;
            }*/
            Integer num = 1;
            /**语音播放次数是否达到3次*/
            String voice = redisService.get(RedisConstant.REDIS_MACHINE_OUT_GEO_VOICE + machineNO);
            if (voice != null) {
                num = Integer.valueOf(voice);
            }
            Integer voiceTime = voiceTimeS == null ? 0 : DateTimeUtil.getSecondDiffer(voiceTimeS);
            Integer sendTime = sendTimeS == null ? 15 : DateTimeUtil.getSecondDiffer(sendTimeS);
            if (voiceTime < 180) {
                if (num > 0 && num <= 3) {
                    if (sendTime >= 15) {
                        //发送语音通知
                        LogUtil.info("发送车体语音通知[" + machineNO + "]");
                        String sNo1 = UUID.randomUUID().toString();
                        terControlService.sendControl(sNo1, machineNO, ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.TER_VOICE_12, "", "出围栏语音播报");
                        /**记录到redis*/
                        redisService.add(RedisConstant.REDIS_MACHINE_OUT_GEO_VOICE + machineNO, String.valueOf(num + 1), 15 * 60);
                        //SystemData.geoViceTice.put(machineNO, num + 1);
                        SystemData.geoSendTime.put(machineNO, DateTimeUtil.getNowTime());
                    } else {
                        LogUtil.info(machineNO + "语音间隔小于15秒");
                    }
                } else {
                    LogUtil.info(machineNO + "超出语音播报次数");
                }
            } else {
                LogUtil.info(machineNO + "voiceTime=" + voiceTime);
                SystemData.geoViceTime.put(machineNO, DateTimeUtil.getNowTime());
                SystemData.geoSendTime.put(machineNO, DateTimeUtil.getNowTime());
                // SystemData.geoViceTice.put(machineNO, 1);
            }
            //}

            /**发送车辆断电指令*/
            String cutPower = redisService.get("cutPower" + machineNO);
            if (cutPower == null) {
                cutPower = "0";
            }
            //log.info("machineNO="+machineNO+",cutPower="+cutPower);
            Integer ci = Integer.valueOf(cutPower);

            String outPower = redisService.get(RedisConstant.REDIS_MACHINE_OUTGEO_PUSH + machineNO);
            if (outPower == null) {
                outPower = "0";
            }
            Integer tmp = Integer.valueOf(outPower);
            //防止断电不成功，连续发送3次断电
            if (ci >= 0 && ci <= 3 && num > 0) {
                ci++;
                String cutTime = SystemData.geoCutTime.get(machineNO);
                if (cutTime == null || "".equals(cutTime)) {
                    SystemData.geoCutTime.put(machineNO, DateTimeUtil.getNowTime());
                }
                tmp++;
                Integer cTime = DateTimeUtil.getSecondDiffer(SystemData.geoCutTime.get(machineNO));
                int sec = 60;
                if (geo.getCutTimeLong() == 0 || cTime >= (geo.getCutTimeLong() * sec)) {
                    //超区断电往回骑(分钟)
                    Integer backCycling = Optional.ofNullable(accountConfigExtDao.selectByAccountIdAndKey(geo.getAccountId(), "temporaryPowerTime"))
                            .map(AccountConfigExt::getParamValue)
                            .map(Integer::parseInt)
                            .filter(x -> x > 0)
                            .orElse(5);
                    String time = redisService.get(String.format("BackCyclingTimeStart#%s", machineNO));
                    if (StringUtils.hasText(time) && (backCycling * sec) > DateTimeUtil.getSecondDiffer(time)) {
                        //配置了断电往回骑  开始往回骑行的时间没有超过配置的时间就不下发锁车指令
                        LogUtil.info(machineNO + "[超区" + backCycling + "分钟内不断电往回骑,开始时间[" + time + "]]");
                        return;
                    }
                    /**判断出围栏速度*/
                    redisService.add("cutPower" + machineNO, String.valueOf(ci),30*60);
                    String serialNo = UUID.randomUUID().toString();
                    LogUtil.info("machineNO=" + machineNO + "控制断电" + "serialNo=" + serialNo);
                    terControlService.sendControl(serialNo, machineNO, ControlTypeConstant.CONTROL_TYPE_CONTROL, ControlTypeConstant.CONTROL_TYPE_UNSTART, "", "出围栏断电");
                    SystemData.geoCutTime.put(machineNO, DateTimeUtil.getNowTime());
                    /**记录已发送断电指令*/
                    redisService.add(RedisConstant.REDIS_MACHINE_OUTGEO_PUSH + machineNO, String.valueOf(tmp), 30 * 60);
                } else {
                    LogUtil.info(machineNO + "[设备断电 " + cTime + "秒延时]");
                }
            } else {
                redisService.add("cutPower" + machineNO, "0",30*60);
            }
        }catch (Exception e){
            log.error("出围栏指令异常",e);
        }


    }

    @Override
    public void insidePush() {
        /**重置车体语音计数*/
        SystemData.geoViceTime.remove(machineNO);
        SystemData.geoSendTime.remove(machineNO);
        SystemData.geoViceTice.remove(machineNO);

        /**控制上电*/
        String serialNo = UUID.randomUUID().toString();
        LogUtil.info("machineNO=" + machineNO + ",控制上电," + "serialNo=" + serialNo);
        //下发指令恢复上电
        terControlService.sendControl(serialNo, machineNO, ControlTypeConstant.CONTROL_TYPE_CONTROL, ControlTypeConstant.CONTROL_TYPE_UNLOCK, "", "入围栏上电");
        redisService.delet(String.format("BackCyclingTimeStart#%s", machineNO));
    }

    @Override
    public void warn() {
        String tmp = redisService.get(RedisConstant.REDIS_MACHINE_NEAR_GEO_WARN + machineNO);
        if (tmp == null) {
            tmp = "0";
        }
        LogUtil.info("发送即将出围栏车体语音预警[" + machineNO + "]");
        String sNo1 = UUID.randomUUID().toString();
        terControlService.sendControl(sNo1, machineNO, ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.TER_VOICE_20, "", "即将出围栏语音预警播报");
        redisService.add(RedisConstant.REDIS_MACHINE_NEAR_GEO_WARN + machineNO, String.valueOf(Integer.valueOf(tmp) + 1), 300);
    }

    @Override
    public void isOut() {
        if (machineNO != null) {
            LogUtil.info("设备在电子围栏外面，车体语音播报[" + machineNO + "]");
            String sNo = UUID.randomUUID().toString();
            terControlService.sendControl(sNo, machineNO, ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.TER_VOICE_3, "", "出围栏语音播报");
        }
    }

    @Override
    public void outForbidden() {

    }

    @Override
    public void insideForbidden() {

    }

}
